home *** CD-ROM | disk | FTP | other *** search
- r
- Title TABS - Align ASCII File
- Page 82,132
- Comment | Version 1.2, April 27, 1984
-
- TABS Command
- -----------------
-
- Purpose: Replace blanks with TAB character(s).
-
- Format: TABS d:input.ext d:output.ext
-
- Remarks: Any TAB characters found are first expanded. Thus, if TABS
- appear within quoted strings - out of context - they will
- be expanded incorrectly.
-
- In replacing blanks with tabs, quoted strings are ignored.
- The maximum logical record size is 255, see MAXREC equate.
- Defacto tab columns are 9,17,25,...
-
- V. Buerg, March, 1984. For public domain use.
-
- ----------------- |
-
- Cseg Segment Public Para 'CODE'
- Assume CS:Cseg,DS:Cseg,ES:Nothing
-
- Tabs Proc Far
- Push DS ;DOS convention
- Sub AX,AX
- Push AX
- Mov CS:Stk_Top,SP ;Save stack ptr to insure return
- Mov AH,30h
- Int 21h ;Verify DOS 2.0 or later
- Mov DX,Offset Sorry
- Cmp AL,2
- Jb Error
-
- Call GetFile ;Get file names
-
- Call OpenIn ;Open input
-
- Call OpenOut ;Open output
-
- Call Inform ;Display "cooking" message
-
- Call GenTab ;Generate tabs
-
- Call Flush ;Empty the output buffer
-
- Mov DX,Offset EofMsg ;Say END-OF-FILE
- Error: Mov SP,Stk_Top ;Insure proper return
- Mov AH,9 ;Print any message
- Int 21h
-
- Call Close ;Close files
-
- Ret ;Return to DOS
- Page
-
- Buflen Equ 16*1024 ;I/O buffer size
- Maxrec Equ 255 ;Longest logical record
-
- S_Quote Equ 34 ;Single quote
- D_Quote Equ 39 ;Double quote
- Tab Equ 9
- Lf Equ 10
- Cr Equ 13
- Eof Equ 1Ah
-
- Rec Db Maxrec Dup (0) ;Current record
- Rlen Dw 0 ;Current record length
- Sw Db 0 ;Number of blanks skipped
- Qsw Db 0 ;Quote switch
- Stk_Top Dw 0 ;SP at entry
-
- MsgIn Db Cr,Lf,'Enter INPUT file name> $'
- Msg1 Db Cr,Lf,'Input failed to open>'
- InKey Db 32,32 ;Keyboard buffer
- Input Db 64 Dup (0),0,'$' ;Drive:path\name.ext
- IHandle Dw 0 ;Input file handle
- Ilen Dw 0 ;Input block length
- Iptr Dw 0 ;Offset to next char
-
- MsgOut Db Cr,Lf,'Enter OUTPUT file name> $'
- Msg2 Db Cr,Lf,'Output failed to open>'
- OutKey Db 32,32
- Output Db 64 Dup (0),0,'$'
- OHandle Dw 0 ;Output file handle
- Olen Dw 0 ;Output block size
- Optr Dw 0 ;Offset to next char
-
- Sorry Db Cr,Lf,'Sorry, PC DOS Version 2 required',Cr,Lf,'$'
- Msg3 Db Cr,Lf,'I/O error reading',Cr,Lf,'$'
- Msg4 Db Cr,Lf,'I/O error writing',Cr,Lf,'$'
- Cooking Db Cr,Lf,'TABBING: $'
- Mark Db ' => $'
- EofMsg Db Cr,Lf,'End of File',Cr,Lf,'$'
- NewLine Db CR,LF,'-$'
-
- Code2 Db 'File not found $'
- Code3 Db 'Path not found $'
- Code4 Db 'Too many files $'
- Code5 Db 'Access denied $'
- Page
-
- ; Replace blanks with tabs
-
- GenTab Proc Near
- Loop: Call GetRec ;Get a record
- Mov CX,Rlen ; its length
- Sub BX,BX ;Output column
- Mov Sw,0 ;No blanks yet
- Mov Qsw,0 ;No quotes yet
- Or CX,CX ;Any data in record?
- Jnz Set1
- Jmp Null ; no, just CR-LF
-
- Set1: Mov SI,Offset Rec ;Look for blanks and
- Wloop: Lodsb ; replace strings of blanks
- Inc BX ; with tab characters
- Cmp AL,D_Quote ;Don't count blanks
- Jne Chk1 ; within single or double
- Xor Qsw,2 ; quoted strings
- Jmp Chk2
-
- Chk1: Cmp AL,S_Quote ;Insert TABs for any
- Jne Chk3 ; blanks skipped before
- Xor Qsw,1 ; a quote
- Chk2: Cmp Sw,0 ;Must re-insert
- Je Check ; any blanks skipped
- Jmp Insert ; if not enough for a TAB
-
- Chk3: Cmp AL,' ' ;Tis a blank?
- ; Jmp Check ;for DETAB
- Jne Check ; no, see if eof
- Test Qsw,3 ;Within quotes?
- Jnz Check
- Inc Sw
- Test BL,07h ;Ready for a tab?
- Jnz Tloop ; no, keep going
- Mov AL,Tab ; yes, send one
- Jmp Copy
-
- Check: Cmp AL,Eof ;End of file?
- Je Done ; yes, all done
- ; Jmp Copy ;for DETAB
- Test Qsw,3 ;When a non-blank is
- Jnz Copy ; encountered, insert a TAB
- Cmp Sw,0 ; if there were blanks
- Je Copy ; before it
- Mov DX,BX
- Dec DL
- Test DL,07h ;If the non-blank is not
- Jnz Insert ; in a TAB column, then
- Push AX ; keeps all the blanks
- Mov AL,Tab
- Call PutChar
- Pop AX
- Jmp Copy
-
- Insert: Push AX ;Insert any blanks that
- Mov DL,Sw ; didn't line up on
- Blanks: Cmp DL,1 ; a TAB column
- Jb None
- Mov AL,' '
- Call PutChar
- Dec DL ;Decr insert count
- Jmp Blanks ; and continue
-
- None: Pop AX ;Get char back
- Copy: Call PutChar ; and write it
- Mov Sw,0 ;Ind not blank
- Tloop: Loop Wloop
- Null: Mov AL,Cr ;Append CR
- Call PutChar
- Mov AL,Lf ; and LF
- Call PutChar
- Jmp Loop
- Done: Ret
- GenTab Endp
- Page
-
- ; Build a logical record
-
- GetRec Proc Near
- Push DI
- Sub DI,DI ;Target record offset
- Mov Rlen,0 ; and length
- Mov Qsw,0 ;Quote indicator
-
- Get1: Call GetChar ;Build up a logical record
- Cmp AL,Cr ; by looking for a CR or LF
- Je Get1 ; as end-of-record
- Cmp AL,Lf
- Je Get7
- Cmp AL,S_Quote ;Don't expand tabs
- Jne Get2 ; found within a
- Xor Qsw,1 ; quoted string
- Get2: Cmp AL,D_Quote
- Jne Get3
- Xor Qsw,2
- Get3: Cmp AL,Tab ;Is it TAB?
- Jne Get5 ; no, pass it
- Test Qsw,3 ;Within quotes?
- Jnz Get5 ; yes, pass it
- Get4: Mov Rec[DI],' ' ;Expand embedded tabs
- Inc DI ; with blanks
- Test DI,0007h
- Jz Get1
- Jmp Get4
-
- Get5: Mov Rec[DI],AL ;Build the record by
- Inc DI ; copying each character
- Cmp DI,Maxrec ; or TABs expanded to blanks
- Jae Get6
- Cmp AL,Eof ;Is it EOF?
- Je Get6 ; yes, all done
- Jmp Get1 ; no, continue
- Get6: Mov Rlen,DI ;Final record length
- Pop DI
- Ret
-
- Get7: Cmp Rec-1[DI],' ' ;Strip trailing blanks
- Jne Get6
- Dec DI
- Jz Get6
- Jmp Get7
-
- GetRec Endp
- Page
- ; Extract one char from record
-
- GetChar Proc Near ;Read char into AL
- Push CX
- Push SI
- Read1: Cmp Ilen,0 ;Any in buffer?
- Je Read ; no, read next block
- Mov SI,Iptr ; yes, get offset in buf
- Push DS
- Mov AX,Seg InBuf ;Copy a char from the
- Mov DS,AX ; input (segment) buffer
- Lodsb
- Pop DS
- Mov Iptr,SI ;Offset for next one
- Dec Ilen ;Decr buffer size left
- Jmp Read4 ; and return with AL
-
- Read: Mov BX,IHandle ;Read a block of data
- Mov CX,BufLen ; into Input (segment) buffer
- Sub DX,DX
- Push DS
- Mov AX,Seg InBuf
- Mov DS,AX
- Mov AH,3Fh
- Int 21h
- Pop DS
- Mov Iptr,0 ;Reset buffer ptr
- Mov Ilen,AX ; and length
- Jc Read2
- Or AX,AX ;Anything read?
- Jnz Read1 ; yes, pick it up
- Mov AL,Eof ; no, return EOF
- Jmp Read4
-
- Read2: Mov DX,Offset Msg3 ;Say I/O ERROR
- Jmp Error
-
- Read4: Pop SI
- Pop CX
- Ret
- GetChar Endp
- Page
-
- ; Block output records
-
- PutChar Proc Near ;Write from AL
- Push AX
- Push BP
- Push BX
- Push CX
- Push DI
- Push DX
- Mov DI,Optr ;Offset in buffer
- Mov DX,Seg OutBuf
- Push ES ;Get buffer segment
- Mov ES,DX
- Stosb ;Place into buffer
- Pop ES
- Inc Olen ;Incr the length
- Mov Optr,DI ; and buffer ptr
- Cmp Olen,Buflen ;Full block?
- Jb Write2 ; no, return
- Mov CX,Buflen ; yes,write it
- Jmp Write3
-
- Flush: Push AX ;Write data left over
- Push BP ; in output buffer
- Push BX
- Push CX
- Push DI
- Push DX
- Mov CX,Olen ;Any left in output?
- Or CX,CX
- Jz Write2
-
- Write3: Mov BX,OHandle ;Get file handle
- Mov BP,CX ;Save size requested
- Sub DX,DX
- Push DS ;Set up DS:DX
- Mov AX,Seg OutBuf ; in buffer segment
- Mov DS,AX
- Mov AH,40h ;Write the block
- Int 21h
- Pop DS
- Mov Optr,0 ;Reset buffer ptr
- Mov Olen,0 ; and size used
- Jc Writer ;Write OK?
- Cmp BP,AX ;Wrote all data?
- Je Write2 ; yes, good
- Writer: Mov DX,Offset Msg4 ; no, say I/O error
- Jmp Error
-
- Write2: Pop DX
- Pop DI
- Pop CX
- Pop BX
- Pop BP
- Pop AX
- Ret
- PutChar Endp
- Page
-
- ; Open input file
-
- OpenIn Proc Near
- Mov DX,Offset Input
- Mov AL,0 ;For input
- Mov AH,3Dh ;Open a file
- Int 21h
- Jnc Openi
- Mov DX,Offset Msg1
- Jmp OpenErr
-
- Openi: Mov IHandle,AX
- Ret
- OpenIn Endp
-
- ; Open output file
-
- OpenOut Proc Near
- Mov DX,Offset Output
- Sub CX,CX ;Normal file attribute
- Mov AH,3Ch ;Create a file
- Int 21h
- Jnc Openo
- Mov DX,Offset Msg2
- Jmp OpenErr
-
- Openo: Mov OHandle,AX
- Ret
- OpenOut Endp
-
- ; Determine why OPEN failed
-
- OpenErr:Cmp AL,2 ;AL has reason code
- Jb Opene
- Cmp AL,5
- Ja Opene
- Sub BX,BX ;Get offset to reason
- Mov BL,AL ; text for open failure
- Mov CL,4
- Shl BX,CL
- Mov AH,9 ;Say OPEN FAILED
- Int 21h
- Mov DX,Offset NewLine
- Mov AH,9
- Int 21h
- Lea DX,Code2-32[BX]
- Opene: Jmp Error
-
- ; Close input/output
-
- Close Proc Near ;Close files
- Mov BX,IHandle ; input
- Mov AH,3Eh
- Int 21h
- Mov BX,OHandle ; output
- Mov AH,3Eh
- Int 21h
- Ret
- Close Endp
- Page
-
- ; Get file names from command line
-
- GetFile Proc Near ;Get file name(s)
- Push CS ;DS points to PSB
- Pop ES ;Now ES points to data
- Mov SI,80h ;Point to command line
- Sub BP,BP ;Indicates first or second name
- Sub CH,CH ;The PSP may contain one or two
- Or CL,Byte Ptr DS:[SI] ; filenames separated by blanks
- Jz GetF5
- Lea DI,ES:Input
- Inc SI
-
- GetF1: Lodsb ;Copy command line to file names
- Cmp AL,' ' ; by skipping leading blanks
- Jne GetF2 ; until a CR is found
- Or BP,BP ; or until the length is zero
- Jz GetF4 ;If a second blank is found,
- Mov AX,2400h ; append zero and dollar sign
- Stosw
- Lea DI,ES:Output ; and it starts the second file name
- Jmp GetF4
-
- GetF2: Cmp AL,Cr ;Is it CR, end of line?
- Je GetF5 ; yes, end of command
- Stosb ; no, save in name
- Mov BP,DI ; and indicate data copied
- GetF4: Loop GetF1
-
- GetF5: Mov AX,2400h ;Append zero and dollar sign
- Stosw
- Mov AX,CS ;When done, set up
- Mov DS,AX ; segment registers
-
- GetF7: Cmp Input,0 ;Any input name?
- Jne GetF8 ; yes, try output name
- Mov DI,Offset MsgIn ; no, ask for one
- Mov SI,Offset InKey
- Call AskName ;Get the input file name
-
- GetF8: Cmp Output,0 ;Any output name?
- Jne GetF9 ; yes, that was easy
- Mov DI,Offset MsgOut ; no, ask for it
- Mov SI,Offset OutKey
- Call AskName ;Get the output name
-
- GetF9: Cmp Word Ptr Output+1,003Ah ;If just a drive is given
- Jne GetFend ; for the output,
- Mov CX,64 ; use the input filename
- Mov DI,Offset Output+2
- Mov SI,Offset Input
- Cmp Input+1,':' ;If drive was given for
- Jne GetF10 ; input, must skip over it
- Dec CL
- Dec CL ;Adjust pointers passed drive
- Dec SI
- Dec SI
- GetF10: Rep Movsb
-
- GetFend:Ret
- GetFile Endp
- Page
-
- ; Ask for file name(s)
-
- AskName Proc Near ;Ask for input file name
- Push DI ;Ptr to prompt msg
- Push SI ;Ptr to reply buffer
- Mov Byte Ptr [SI],64 ;Reply length
- Ask1: Mov DX,DI
- Mov AH,9 ;Print the prompt msg
- Int 21h
- Mov DX,SI ;Read console reply
- Mov AH,10
- Int 21h
- Sub BX,BX ;If a reply is given,
- Add BL,1[SI] ; append a zero as the
- Jz Ask1 ; ASCIIZ name stopper
- Mov Word Ptr 2[SI][BX],2400h
- Mov Word Ptr 0[SI],' ' ;Clear error message part
- Pop SI
- Pop DI
- Ret
- AskName Endp
-
- ; Display "cooking" message
-
- Inform Proc Near
- Mov AH,9
- Mov DX,Offset Cooking
- Int 21h
- Mov AH,9
- Mov DX,Offset Input
- Int 21h
- Mov AH,9
- Mov DX,Offset Mark
- Int 21h
- Mov AH,9
- Mov DX,Offset Output
- Int 21h
- Ret
- Inform Endp
-
- Tabs Endp
-
-
- Cseg Ends
-
- Stk Segment Byte Stack 'STACK'
- Db 128 Dup (?)
- Stk Ends
-
- InBuf Segment Public Byte 'DATA'
- Db Buflen Dup (?)
- InBuf Ends
-
- OutBuf Segment Public Byte 'DATA'
- Db Buflen Dup (?)
- OutBuf Ends
-
- End Tabs
-
-
- Press ENTER to continue: Segment Public Byte 'DATA'
- Db Buflen Dup (?)